package drongo.desktop.tools
{
	import drongo.desktop.tools.events.TraceableEvent;
	import drongo.desktop.utils.FileUtil;
	import drongo.desktop.utils.StringUtil;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.JPEGEncoderOptions;
	import flash.display.Loader;
	import flash.display.PNGEncoderOptions;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.filesystem.File;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.net.FileFilter;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	public class ImageEncode extends EventDispatcher
	{
		public static const JPG:String="jpg";
		public static const PNG:String="png";
		
		/**
		 * 图片改变大小时的填充方式，强行缩放到新尺寸
		 */		
		public static const ZOOM:int=0;
		/**
		 * 图片改变大小时的填充方式，不变 
		 */
		public static const UNCHANGED:int=1;
		public function ImageEncode()
		{
			super();
		}
		/**
		 * 批量处理 
		 * @param arg
		 */		
		public function batch(arg:Array):void{
			encode.apply(null,arg);
		}
		/**
		 * 图片编码 
		 * 暂时只支持png和jpg之间互转
		 * @param source				文件地址/文件夹地址/二进制/BitmapData  
		 * @param target				转换后的图片存放地址或存放文件夹地址
		 * @param type				转换到什么格式
		 * @param data  				转换参数 当转换png时 传入true/false 来指示是否开启fastCompression   当转换jpg时 传入0-100 来指示图片 quality
		 * @param changeSize		改变大小,只有在单个文件时有用
		 * @param fillMode			填充方式,只有在改变大小时有用
		 * @param width				新宽度，如果需要改变的话，只有在改变大小时有用
		 * @param heigth				新高度，如果需要改变的话，只有在改变大小时有用
		 */		
		public function encode(source:Object,target:String,type:String,data:Object=null,changeSize:Boolean=false,fillMode:int=UNCHANGED,width:Number=NaN,heigth:Number=NaN):void{	
			if(source is BitmapData){
				var bitmapData:BitmapData= source as BitmapData;
				if(changeSize){
					if(bitmapData.width!=width||bitmapData.height!=heigth){
						var newBitmapData:BitmapData=new BitmapData(width,heigth,true,0);
						if(fillMode==ZOOM){
							HELP_MATRIX.identity();
							HELP_MATRIX.a=width/bitmapData.width;
							HELP_MATRIX.d=heigth/bitmapData.height
							newBitmapData.draw(bitmapData,HELP_MATRIX,null,null,null,true);
						}else{
							HELP_POINT.x=0;
							HELP_POINT.y=0;
							newBitmapData.copyPixels(bitmapData,bitmapData.rect,HELP_POINT);
						}
						bitmapData=newBitmapData;
					}
				}
				var compressor:Object;
				var byte:ByteArray;
				if(type==PNG){
					compressor=new PNGEncoderOptions(data!=null?data:false);
				}else{
					compressor=new JPEGEncoderOptions();
					compressor.quality=uint(data)>0?uint(data):100;
				}
				byte=bitmapData.encode(bitmapData.rect,compressor);
				encode(byte,target,type,null);
				return;
			}
			
			var targetFile:File=new File(target);
			if(source is String){
				var sourceFile:File=new File(source as String);
				if(!sourceFile.isDirectory){
					if(targetFile.extension==null){
						this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"ImageEncode","source参数为文件时target也必须是一个文件路径"));
						return;
					}
					this._source=source as String;
					this._target=target;
					this._type=type;
					this._data=data;
					this._changeSize=changeSize;
					this._fillMode=fillMode;
					this._width=width;
					this._heigth=heigth;
					_startLoad();
				}else{
					if(targetFile.extension!=null){
						this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"ImageEncode","source参数为文件夹时target也必须是一个文件夹路径"));
						return;
					}
					var fileList:Array=FileUtil.getDirectoryListing(sourceFile,new FileFilter("image","*.png;*.jpg"));
					if(fileList.length>0){
						var argumentsList:Vector.<Array>=new Vector.<Array>();
						var args:Array;
						var relativePath:String;
						for each (var i:File in fileList) 
						{
							args=[];
							relativePath=sourceFile.getRelativePath(i);
							args.push(
								i.nativePath,
								target+File.separator+StringUtil.replaceBySeparator(relativePath,type,1),
								type,
								data);
							argumentsList.push(args);
						}
						var batch:Batch=new Batch(ImageEncode,"batch");
						TraceableEvent.AddEvents(batch,_batchHandler);
						batch.start(argumentsList);
					}
				}
			}else if(source is ByteArray){
				if(targetFile.extension==null){
					this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"ImageEncode","source参数为二进制时target也必须是一个文件路径"));
					return;
				}
				var fileSave:FileSave=new FileSave();
				TraceableEvent.AddEvents(fileSave,_fileSaveHandler);
				fileSave.save(source,target);
			}
		}
		private function _fileSaveHandler(e:TraceableEvent):void{
			if(e.type==TraceableEvent.COMPLETE){
				var fileSave:FileSave=e.target as FileSave;
				TraceableEvent.RemoveEvents(fileSave,_fileSaveHandler);
				this.dispatchEvent(new TraceableEvent(TraceableEvent.COMPLETE,"ImageEncode","Save",0,0,e));
			}else if(e.type==TraceableEvent.ERROR){
				this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"ImageEncode","Save",0,0,e));
			}else{
				this.dispatchEvent(new TraceableEvent(TraceableEvent.PROGRESS,"ImageEncode","Save",e.index,e.total,e));
			}
		}
		private function _batchHandler(e:TraceableEvent):void{
			if(e.type==TraceableEvent.COMPLETE){
				var batch:Batch=e.target as Batch;
				TraceableEvent.RemoveEvents(batch,_batchHandler);
				
				this.dispatchEvent(new TraceableEvent(TraceableEvent.COMPLETE,"ImageEncode","Batch",0,0,e));
			}else if(e.type==TraceableEvent.ERROR){
				this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"ImageEncode","Batch",0,0,e));
			}else{
				this.dispatchEvent(new TraceableEvent(TraceableEvent.PROGRESS,"ImageEncode","Batch",e.index,e.total,e));
			}
		}
		private var _loader:Loader;
		private var _target:String;
		private var _source:String;
		private var _type:String;
		private var _data:Object;
		private var _changeSize:Boolean=false;
		private var _fillMode:int=UNCHANGED;
		private var _width:Number=NaN;
		private var _heigth:Number=NaN;

		private var HELP_POINT:Point=new Point();
		private var HELP_MATRIX:Matrix=new Matrix();
		private function _startLoad():void{
			if(!_loader){
				_loader=new Loader();
				_loader.contentLoaderInfo.addEventListener(Event.COMPLETE,_imageLoadHandler);
				_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,_imageLoadHandler);
				_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,_imageLoadHandler);
			}
			_loader.load(new URLRequest(_source));
		}
		private function _imageLoadHandler(e:Event):void{
			if(e is IOErrorEvent){
				this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"ImageEncode"," soucre:"+this._source+"加载文件出错！"));
			}else if(e is ProgressEvent){
				var bytesLoaded:Number=ProgressEvent(e).bytesLoaded;
				var bytesTotal:Number=ProgressEvent(e).bytesTotal
				this.dispatchEvent(new TraceableEvent(TraceableEvent.PROGRESS,"ImageEncode","load",bytesLoaded*.5,bytesTotal*.5));
			}else{
				encode(Bitmap(_loader.content).bitmapData,this._target,this._type,_data,this._changeSize,this._fillMode,this._width,this._heigth);
				_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,_imageLoadHandler);
				_loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,_imageLoadHandler);
				_loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS,_imageLoadHandler);
				_loader=null;
			}
		}
	}
}